/**
 * \file Stack.h
 * \brief Stack definition and declaration class
 * \author Edouard ROGE
 * \date 13 september 2012
 */

#ifndef _STACK_
#define _STACK_

#include "ArrayBase.h"

/**
 * \class Stack
 * \brief Stack class with template, similar to std::stack<T>
 */
template <class T>
class Stack : public ArrayBase<T>
{
public:

	/**
	 * \fn Stack();
	 * \brief Default constructor
	 */
	Stack();

	/**
	 * \fn Stack(uint32 _iSize);
	 * \param _iSize new array's size
	 * \brief constructor, Resize array with the size in param
	 */
	Stack(uint32 _iSize);

	/**
	 * \fn Stack(const Stack<T> & _tStack);
	 * \param _tStack array to copy
	 * \brief Copy constructor
	 */
	Stack(const Stack<T> & _tStack);

	/**
	 * \fn ~Stack();
	 * \brief Destructor
	 */
	~Stack();

	/**
	 * \fn Stack<T> & operator = (const Stack<T> & _tStack);
	 * \param _tStack array to copy
	 * \return (*this) with new values
	 * \brief operator =
	 */
	Stack<T> & operator = (const Stack<T> & _tStack);

	/**
	 * \fn void Push(const T & _element);
	 * \param _element new element to push at the top of the stack
	 * \brief push a new element a the top of the stack
	 */
	void Push(const T & _element);

	/**
	 * \fn T Pop();
	 * \return the top element
	 * \brief pop the top element out of the stack
	 */
	T Pop();

	/**
	 * \fn const T & Top() const;
	 * \return the top element
	 * \brief get the top element
	 */
	const T & Top() const;

	/**
	 * \fn template < class S > friend bool operator == (const Stack<S> & _tStack1, const Stack<S> & _tStack2);
	 * \param _tStack1 Stack1
	 * \param _tStack2 Stack2
	 * \return true if Stack1 is equal to Stack2
	 * \brief operator ==
	 */
	template < class S > friend bool operator == (const Stack<S> & _tStack1, const Stack<S> & _tStack2);

	/**
	 * \fn template < class S > friend bool operator != (const Stack<S> & _tStack1, const Stack<S> & _tStack2);
	 * \param _tStack1 Stack1
	 * \param _tStack2 Stack2
	 * \return true if Stack1 is not equal to Stack2
	 * \brief operator !=
	 */
	template < class S > friend bool operator != (const Stack<S> & _tStack1, const Stack<S> & _tStack2);

};

template< class T >
Stack<T>::Stack()
: ArrayBase<T>()
{
}

template< class T >
Stack<T>::Stack(uint32 _iSize)
: ArrayBase<T>(_iSize)
{
}

template< class T >
Stack<T>::Stack(const Stack<T> & _tStack)
{
	_Clone(_tStack.m_tArray, _tStack.m_iSize);
}

template< class T >
Stack<T>::~Stack()
{

}

template< class T >
Stack<T> & Stack<T>::operator = (const Stack<T> & _tStack)
{
	_Clone(_tStack.m_tArray, _tStack.m_iSize);
	return (*this);
}

template< class T >
void Stack<T>::Push(const T & _element)
{
	ArrayBase<T>::_Insert(ArrayBase<T>::m_tArray+ArrayBase<T>::m_iSize, _element);
}

template< class T >
T Stack<T>::Pop()
{
	T res = ArrayBase<T>::m_tArray[ArrayBase<T>::m_iSize-1];
	ArrayBase<T>::_Remove(ArrayBase<T>::m_tArray+(ArrayBase<T>::m_iSize-1));
	return res;
}

template< class T >
const T & Stack<T>::Top() const
{
	return ArrayBase<T>::m_tArray[ArrayBase<T>::m_iSize-1];
}

/**
 * \fn template < class S > bool operator == (const Stack<S> & _tStack1, const Stack<S> & _tStack2);
 * \param _tStack1 Stack1
 * \param _tStack2 Stack2
 * \return true if Stack1 is equal to Stack2
 * \brief operator ==
 */
template < class S >
bool operator == (const Stack<S> & _tStack1, const Stack<S> & _tStack2)
{
	uint32 iSize1 = _tStack1.Size();
	if( iSize1 == _tStack2.Size() )
	{
		for(uint32 i=0; i < iSize1; ++i)
			if( _tStack1[i] != _tStack2[i] )
				return false;

		return true;
	}

	return false;
}

/**
 * \fn template < class S > bool operator != (const Stack<S> & _tStack1, const Stack<S> & _tStack2);
 * \param _tStack1 Stack1
 * \param _tStack2 Stack2
 * \return true if Stack1 is not equal to Stack2
 * \brief operator !=
 */
template < class S >
bool operator != (const Stack<S> & _tStack1, const Stack<S> & _tStack2)
{
	return !(_tStack1==_tStack2);
}

#endif // _STACK_
